/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.rcs.adslmonitor;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * http://192.168.1.1/SysStatistics_ADSL.html
 *
 * @author pablo
 */
public abstract class ADSLStatus {

  public static enum KEYS {

    UP_STREAM("Up Stream"),
    ATTAINABLE_UP_RATE("Attainable Up Rate"),
    ATTENUATION_UP_STREAM("Attenuation Up Stream(db)"),
    SNR_MARGIN_UP_STREAM("SNR Margin Up Stream(db)"),
    DOWN_STREAM("Down Stream"),
    ATTAINABLE_DOWN_RATE("Attainable Down Rate"),
    ATTENUATION_DOWN_STREAM("Attenuation Down Stream(db)"),
    SNR_MARGIN_DOWN_STREAM("SNR Margin Down Stream(db)"),
    ADSL_MODE("Adsl Mode"),
    ADSL_LINE_STATUS("Adsl Line Status"),
    // Optionals
    UAS("UAS"),
    CRC_ERRORS("CRC Errors"),
    ES("ES"),
    SES("SES"),
    DSP_VERSION("DSP Version");
    private String key;

    KEYS(String key) {
      this.key = key;
    }

    public String getKey() {
      return key;
    }
  }

  private EventMulticaster<ADSLStatusListener> listeners = new EventMulticaster<ADSLStatusListener>(ADSLStatusListener.class);
  private Timer timer;
  private String user;
  private String password;
  private URL routerURL;
  private String routerName;
  private String lastError;
  private Map<String, String> data = new HashMap<String, String>();

  public ADSLStatus(String routerName) {
    this.routerName = routerName;
    this.lastError = "Conectando..." ;
  }

  protected void setLastError(Throwable th) {
    lastError = th.getLocalizedMessage();
  }

  protected void setLastError(String error) {
    lastError = error;
  }

  public String getLastError() {
    return lastError;
  }

  public boolean hasError() {
    return getLastError() != null;
  }

  protected void put(KEYS key, String value) {
    data.put(key.getKey(), value);
  }

  public String get(KEYS key) {
    return data.get(key.getKey()) ;
  }

  public double getAsDouble(KEYS key) {
    try {
      return Double.parseDouble(get(key));
    } catch (Throwable ex) {
      return 0;
    }
  }

  protected void cleanUnit(KEYS key) {
    String txt = get(key);
    txt = txt.trim();
    String[] values = txt.split(" ");

    if (values.length > 1)
      txt = values[0];

    put(key, txt);
  }

  protected void resetUnits() {
    for (String keyStr : data.keySet())
      data.put(keyStr, "0") ;
  }
  
  /**
   * @return the routerName
   */
  public String getRouterName() {
    return routerName;
  }

  /**
   * @return the user
   */
  public String getUser() {
    return user;
  }

  /**
   * @param user the user to set
   */
  public void setUser(String user) {
    this.user = user;
  }

  /**
   * @return the password
   */
  public String getPassword() {
    return password;
  }

  /**
   * @param password the password to set
   */
  public void setPassword(String password) {
    this.password = password;
  }

  /**
   * @return the routerURL
   */
  public URL getRouterURL() {
    return routerURL;
  }

  public URL getRouterURLForBrowser() throws MalformedURLException {
    URL url = getRouterURL() ;
    String txt = url.toString() ;
    String auth = getUser() + ":" + getPassword() + "@";
    int index = txt.indexOf("//") ;
    String protocol = txt.substring(0, index + 2) ;
    String restString = txt.substring(index + 2) ;

    return new URL(protocol + auth + restString) ;
  }
  
  /**
   * @param routerURL the routerURL to set
   */
  public void setRouterURL(URL routerURL) {
    this.routerURL = routerURL;
  }

  public void setRouterURL(String routerURL) {
    try {
      setRouterURL(new URL(routerURL));
    } catch (MalformedURLException ex) {
      Logger.getLogger(ADSLStatus.class.getName()).log(Level.SEVERE, null, ex);
      lastError = ex.getLocalizedMessage();
    }
  }

  public boolean refresh() {
    setLastError((String) null);

    boolean result = onRefresh();

    listeners.getMulticaster().statusChanged(new EventObject(this));
    return result;
  }

  protected abstract boolean onRefresh();

  /**
   * Listener are calling out of EDT
   *
   * @param l
   */
  public void addListener(ADSLStatusListener l) {
    listeners.addListener(l);
  }

  public void removeListener(ADSLStatusListener l) {
    listeners.removeListener(l);
  }

  public void stopRefreshRate() {
    if (null != timer)
      timer.cancel();

    timer = null;
  }

  public void setRefreshRate(int seconds) {
    if (null == timer)
      timer = new Timer();
    else
      timer.cancel();

    timer.schedule(new TimerTask() {
      @Override
      public void run() {
        try {
          refresh();
        } catch (Throwable th) {
          th.printStackTrace();
        }
      }
    }, seconds * 1000, seconds * 1000);
  }
}
